package org.summerframework.component.security.session.resolver;

import org.summerframework.component.security.session.config.SessionIdAutoConfiguration;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.session.web.http.CookieHttpSessionIdResolver;
import org.springframework.session.web.http.CookieSerializer;
import org.springframework.session.web.http.HeaderHttpSessionIdResolver;
import org.springframework.session.web.http.HttpSessionIdResolver;
import org.springframework.web.bind.ServletRequestUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;

/**
 * 兼容cookie模式, 与url参数
 * <p>
 * head
 * 支持sessionId与jwt两种, jwt必须携带Breaker 开头
 * <code>
 * 如: Breaker eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxMjMiLCIxMjMiOiIhMjMiLCJzZXNzaW9uSWQiOiIxMjMiLCJqdGkiOiIxMjMifQ.-oHAenTiTsGYlfAVGgqDfY2jHob7PLsuVsRB0hsCyGU4qqtPvb42qkqjWJisExknBLNtqo6-FU6ohClqV-3WTA
 * </code>
 * <p>
 * url
 * 参数名 {@link #setHeaderHttpSessionIdProperty(SessionIdAutoConfiguration.HeaderHttpSessionIdProperty)}
 * cookie {@link CookieSerializer} 与默认的保持一致
 * <p>
 * check为true是, 只获取一个sessionId,
 * 为false时, 三种模式都获取, 第一个有效的session为准
 * <p>
 * head > url > cookie
 *
 * @author 石超
 * @version v1.0.0
 */
public class WebSessionIdResolver implements HttpSessionIdResolver {

    private CookieHttpSessionIdResolver cookieHttpSessionIdResolver;
    private HeaderHttpSessionIdResolver headerHttpSessionIdResolver;
    private SessionIdAutoConfiguration.UrlHttpSessionIdProperty urlHttpSessionIdProperty;

    public WebSessionIdResolver() {
    }

    @Override
    public List<String> resolveSessionIds(HttpServletRequest request) {
        List<String> list = new ArrayList<>();

        //header方式获取
        if (headerHttpSessionIdResolver != null) {
            add(list, headerHttpSessionIdResolver.resolveSessionIds(request));
        }

        //url方式获取
        if (urlHttpSessionIdProperty != null) {
            add(list, ServletRequestUtils.getStringParameter(request, urlHttpSessionIdProperty.getName(), ""));
        }

        //cookie方式获取
        if (cookieHttpSessionIdResolver != null) {
            add(list, cookieHttpSessionIdResolver.resolveSessionIds(request));
        }

        return list;
    }

    private void add(List<String> sessionIds, String sessionId) {
        if (StringUtils.isNotBlank(sessionId)) {
            sessionIds.add(sessionId);
        }
    }

    private void add(List<String> sessionIds, List<String> sessionId) {
        if (CollectionUtils.isNotEmpty(sessionId)) {
            sessionIds.addAll(sessionId);
        }
    }

    @Override
    public void setSessionId(HttpServletRequest request, HttpServletResponse response, String sessionId) {
        if (headerHttpSessionIdResolver != null) {
            headerHttpSessionIdResolver.setSessionId(request, response, sessionId);
        }

        if (cookieHttpSessionIdResolver != null) {
            cookieHttpSessionIdResolver.setSessionId(request, response, sessionId);
        }
    }

    @Override
    public void expireSession(HttpServletRequest request, HttpServletResponse response) {
        if (this.cookieHttpSessionIdResolver != null) {
            this.cookieHttpSessionIdResolver.expireSession(request, response);
        }
    }

    @Autowired(required = false)
    public void setCookieSerializer(CookieSerializer cookieSerializer) {
        this.cookieHttpSessionIdResolver = new CookieHttpSessionIdResolver();
        this.cookieHttpSessionIdResolver.setCookieSerializer(cookieSerializer);
    }

    @Autowired(required = false)
    public void setHeaderHttpSessionIdProperty(SessionIdAutoConfiguration.HeaderHttpSessionIdProperty headerHttpSessionIdProperty) {
        if (StringUtils.isNotBlank(headerHttpSessionIdProperty.getName())) {
            this.headerHttpSessionIdResolver = new HeaderHttpSessionIdResolver(headerHttpSessionIdProperty.getName());
        }
    }

    @Autowired(required = false)
    public void setUrlHttpSessionIdProperty(SessionIdAutoConfiguration.UrlHttpSessionIdProperty urlHttpSessionIdProperty) {
        if (StringUtils.isNotBlank(urlHttpSessionIdProperty.getName())) {
            this.urlHttpSessionIdProperty = urlHttpSessionIdProperty;
        }
    }
}
